#ifndef SLEEQHASH_BDB_H
#define SLEEQHASH_BDB_H

#include "sleeabstract_bdb.h"
#include <QStack>
#include <QDebug>

#define OUTS_MODE QIODevice::WriteOnly
#define INS_MODE QIODevice::ReadOnly
#define PRIM_FLD        -1

#define CONSTR_OP_LESS  -1
#define CONSTR_OP_EQ     0
#define CONSTR_OP_MORE   1

#define CONSTR_INTER_AND   1
#define CONSTR_INTER_OR    0

typedef   QHash<int, QVariant>  SLEE_HDB_REC;
typedef   QList< SLEE_HDB_REC > SLEE_HDB_REC_LST;

class SLEEDB_SHARED SleeQHash_BDB;
class SLEEDB_SHARED SleeQHash_Constrain;

class SecDb: public Db
{
public:
    int indx;
    SecDb(DbEnv *p_env, u_int32_t flags): Db(p_env, flags) {indx = -1;}
};


class SLEEDB_SHARED SleeQHash_Constrain
{
    QVariantList mqv_data_lst;
    QList<int> m_flds_lst;
    QString mqstr_process;
    SLEE_HDB_REC mqh_data;
    int m_pos;
    bool do_print;
    QChar get_char();
    QVariant get_var();
    bool process(int depth = 0);

public:
   SleeQHash_Constrain():m_pos(0), do_print(false) {}
   inline void set_data(const QVariantList &qv_data_lst) {mqv_data_lst = qv_data_lst; }
   inline void append_data(const QVariant &qv_data) {mqv_data_lst.append(qv_data);}

   inline void set_flds(const QList<int> &flds_lst) {m_flds_lst = flds_lst;}
   inline void append_fld(const int fld) {m_flds_lst.append(fld);}

   inline void append(const QVariant &qv_data, const int fld)
   {
       mqv_data_lst.append(qv_data);
       m_flds_lst.append(fld);
   }

   inline void clear(bool clear_process_string = false)
   {
       mqv_data_lst.clear();
       m_flds_lst.clear();
       if(clear_process_string)
           mqstr_process.clear();
   }
    //using operands: = < > () | &
    //using arguments: $indx% - data from qv_data list
    //                 $indx# - data from flds list
    //                 where indx is index from list
   inline void set_process_string(const QString &str) {mqstr_process = str; }
   inline void append_process_string(const QString &str) {mqstr_process += str;}

   bool process_data(const SLEE_HDB_REC &qh_data);

};

class SLEEDB_SHARED SleeQHash_BDB : public SleeAbstract_BDB
{
    QStringList           m_fld_names;
    QList<QVariant::Type> m_fld_types;

    QHash <int, SecDb *> m_hashIndexDb;
    bool    mb_dup_support;
    static QByteArray gm_qb_buffer;
    void pre_initDb();
    void post_initDb();
    void pre_closeDb();
    void syncDb();
    static void qb_to_qh(QByteArray &buffer, SLEE_HDB_REC &hash);
    static void qh_to_qb(QByteArray &buffer, const SLEE_HDB_REC &hash);

    static int secondary_key_extractor(Db *sDb, const Dbt *pkey, const Dbt *pdata, Dbt *skey);
    static bool isRelevant(QVariant &qv_data, QVariant &qv_request);
public:
    SleeQHash_BDB();
    void setupFields(const QStringList &lstNames, const QList<QVariant::Type> &fld_types, const QList<int> &lstIndexFlds);
    bool is_valid_data(const SLEE_HDB_REC &qh_data);
    QVariant putData(const SLEE_HDB_REC &qh_data, const QVariant *pqv_key=NULL);
     int getData(SLEE_HDB_REC_LST &lst_data,const QVariant &qv_key);
     int removeData(const SLEE_HDB_REC &qh_data, const QVariant &qv_pkey);
    QVariantList findRelevantData(int i_fld, QVariant &qv_request, SLEE_HDB_REC_LST *pqh_data_lst = NULL, SleeQHash_Constrain *p_contsrain = NULL);
    QVariantList findDataRange(int i_fld,
                               QVariant *pqv_min = NULL, bool do_eq_min = true,
                               QVariant *pqv_max = NULL, bool do_eq_max = false,
                               SLEE_HDB_REC_LST *pqh_data_lst = NULL, SleeQHash_Constrain *p_contsrain = NULL);
    QVariantList findDataEq(int i_fld, const QVariant &qv_request, SLEE_HDB_REC_LST *pqh_data_lst = NULL, SleeQHash_Constrain *p_contsrain = NULL);
    inline const QStringList &get_fld_names() {return m_fld_names;}
    void recovery_db();
    void qDebugDumpSec(int i_fld);
    void qDebugDumpBase(bool b_dump_duta = false);
};

#endif // SLEEQHASH_BDB_H
